using System.ServiceModel;
using Albatross.Common.Messaging;
using Albatross.Common.WCF;
using System.ServiceModel.Channels;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Albatross.ClientSide.WCF
{
	public class RequestProcessorProxyForDotNetClient : ClientBase<IWcfRequestProcessorForDotNetClient>, IRequestProcessor
	{
		public RequestProcessorProxyForDotNetClient()
		{
		}

		public RequestProcessorProxyForDotNetClient( string endpointConfigurationName )
			: base( endpointConfigurationName )
		{
		}

		public RequestProcessorProxyForDotNetClient( string endpointConfigurationName, string remoteAddress )
			: base( endpointConfigurationName, remoteAddress )
		{
		}

		public RequestProcessorProxyForDotNetClient( string endpointConfigurationName, EndpointAddress remoteAddress )
			: base( endpointConfigurationName, remoteAddress )
		{
		}

		public RequestProcessorProxyForDotNetClient( Binding binding, EndpointAddress remoteAddress )
			: base( binding, remoteAddress )
		{
		}

		public RequestProcessorProxyForDotNetClient( InstanceContext callbackInstance )
			: base( callbackInstance )
		{
		}

		public RequestProcessorProxyForDotNetClient( InstanceContext callbackInstance, string endpointConfigurationName )
			: base( callbackInstance, endpointConfigurationName )
		{
		}

		public RequestProcessorProxyForDotNetClient( InstanceContext callbackInstance, string endpointConfigurationName, string remoteAddress )
			: base( callbackInstance, endpointConfigurationName, remoteAddress )
		{
		}

		public RequestProcessorProxyForDotNetClient( InstanceContext callbackInstance, string endpointConfigurationName, EndpointAddress remoteAddress )
			: base( callbackInstance, endpointConfigurationName, remoteAddress )
		{
		}

		public RequestProcessorProxyForDotNetClient( InstanceContext callbackInstance, Binding binding, EndpointAddress remoteAddress )
			: base( callbackInstance, binding, remoteAddress )
		{
		}

		public Response[] Process( params Request[] requests )
		{
			return Channel.Process( requests );
		}

		public virtual void ProcessAsync( Action<List<Response>> callback, params Request[] requestsToProcess )
		{
			var worker = new System.ComponentModel.BackgroundWorker();
			worker.DoWork += new System.ComponentModel.DoWorkEventHandler( worker_DoWork );
			worker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler( worker_RunWorkerCompleted );

			var args = new object[ 2 ];
			args[ 0 ] = requestsToProcess;
			args[ 1 ] = callback;
			worker.RunWorkerAsync( args );
		}

		protected virtual void worker_DoWork( object sender, System.ComponentModel.DoWorkEventArgs e )
		{
			try
			{
				Request[] requests = ( Request[] )( ( object[] )e.Argument )[ 0 ];
				var results = Process( requests );
				( ( object[] )e.Argument )[ 0 ] = results;
				e.Result = e.Argument;
			}
			catch ( System.Exception ex )
			{
				var ErrorResponse = new Albatross.Common.Messaging.ErrorResponse();
				ErrorResponse.StatusInfo = ex.ToString();
				ErrorResponse.StatusType = ( Int32 )Albatross.Common.Exceptions.ErrorType.DispatcherUnHandledException;
				Response[] ErrorResponses = new Response[] { ErrorResponse };

				( ( object[] )e.Argument )[ 0 ] = ErrorResponses;
				e.Result = e.Argument;
			}
		}

		protected virtual void worker_RunWorkerCompleted( object sender, System.ComponentModel.RunWorkerCompletedEventArgs e )
		{
			Action<List<Response>> callback = ( Action<List<Response>> )( ( object[] )e.Result )[ 1 ];
			Response[] responses = ( Response[] )( ( object[] )e.Result )[ 0 ];
			callback( responses.ToList() );
		}

		

		public void Dispose()
		{
			try
			{
				Close();
			}
			catch ( Exception )
			{
				Abort();
			}
		}
	}
}
